from cryptography.fernet import Fernet
import tkinter as tk
from tkinter import ttk, messagebox, simpledialog, filedialog
import json
import pyperclip
import os

# 生成密钥并保存到文件
def generate_key():
    key = Fernet.generate_key()
    with open("secret.key", "wb") as key_file:
        key_file.write(key)

# 加载密钥
def load_key():
    return open("secret.key", "rb").read()

# 加密数据
def encrypt_data(data, key):
    f = Fernet(key)
    encrypted_data = f.encrypt(data.encode())
    return encrypted_data

# 解密数据
def decrypt_data(encrypted_data, key):
    f = Fernet(key)
    decrypted_data = f.decrypt(encrypted_data).decode()
    return decrypted_data

class TextManager:
    def __init__(self):
        if not os.path.exists("secret.key"):
            generate_key()
        
        self.window = tk.Tk()
        self.window.title('文本管理器')
        self.window.geometry('800x480')
        self.window.resizable(False, False)
        
        screen_width = self.window.winfo_screenwidth()
        screen_height = self.window.winfo_screenheight()
        x = (screen_width - 800) // 2
        y = (screen_height - 480) // 2
        self.window.geometry(f'800x480+{x}+{y}')

        self.sections = ['Temp', 'Live', 'Game', 'Study']  # 添加 'Study'
        self.current_section = 'Temp'
        self.section_tags = {section: [] for section in self.sections}
        self.tag_texts = {}

        self.left_frame = ttk.Frame(self.window, width=200)
        self.left_frame.pack(side='left', fill='y', padx=5, pady=5)

        self.tag_input_frame = ttk.Frame(self.left_frame)
        self.tag_input_frame.pack(fill='x', pady=5)

        self.tag_input = ttk.Entry(self.tag_input_frame, width=25)
        self.tag_input.pack(side='top', padx=2)
        self.tag_input.bind('<Return>', self.add_tag)

        self.add_tag_btn = ttk.Button(self.tag_input_frame, text='添加标签', command=self.add_tag)
        self.add_tag_btn.pack(side='left', padx=2)

        self.delete_tag_btn = ttk.Button(self.tag_input_frame, text='删除标签', command=self.delete_tag)
        self.delete_tag_btn.pack(side='right', padx=2)

        self.tag_listbox = tk.Listbox(self.left_frame, width=25, height=20, selectbackground='white', selectforeground='green', fg='black')
        self.tag_listbox.pack(fill='both', expand=True)
        self.tag_listbox.bind('<<ListboxSelect>>', self.on_tag_select)

        self.right_frame = ttk.Frame(self.window)
        self.right_frame.pack(side='left', fill='both', expand=True, padx=5, pady=5)

        self.input_frame = ttk.Frame(self.right_frame)
        self.input_frame.pack(pady=10, padx=10, fill='x')

        self.text_input = ttk.Entry(self.input_frame, width=30)
        self.text_input.pack(side='left', padx=5)
        self.text_input.bind('<Return>', lambda e: self.add_text())

        

        self.add_btn = ttk.Button(self.input_frame, text='添加文本', command=self.add_text)
        self.add_btn.pack(side='left')

        self.delete_btn = ttk.Button(self.input_frame, text='删除文本', command=self.delete_text)
        self.delete_btn.pack(side='left', padx=5)

        self.import_btn = ttk.Button(self.input_frame, text='导入TXT', command=self.import_txt)
        self.import_btn.pack(side='left', padx=5)

        self.export_btn = ttk.Button(self.input_frame, text='导出TXT', command=self.export_txt)
        self.export_btn.pack(side='right', padx=5)



        self.section_frame = ttk.Frame(self.right_frame)
        self.section_frame.pack(pady=5, padx=10, fill='x')

        self.rename_frame = ttk.Frame(self.left_frame)
        self.rename_frame.pack(side='bottom', fill='x', pady=5)

        # 创建右键菜单
        self.tag_menu = tk.Menu(self.window, tearoff=0)
        for section in self.sections:
            self.tag_menu.add_command(label=f'移动到 {section}', command=lambda s=section: self.move_tag_to_section(s))
        
        self.tag_listbox.bind('<Button-3>', self.show_tag_menu)

        self.section_buttons = {}
        style = ttk.Style()
        style.configure('Selected.TButton', background='#90EE90')
        style.configure('Normal.TButton', background='SystemButtonFace')
        
        for section in self.sections:
            btn = ttk.Button(self.section_frame, text=section,
                           command=lambda s=section: self.switch_section(s),
                           style='Normal.TButton')
            btn.pack(side='left', padx=5)
            self.section_buttons[section] = btn

        self.listbox = tk.Listbox(self.right_frame, width=40, height=15)
        self.listbox.pack(pady=10, padx=10, fill='both', expand=True)
        self.listbox.bind('<<ListboxSelect>>', self.on_select)

        self.tag_listbox.bind('<Double-1>', self.rename_tag)

        self.last_key_time = 0
        self.listbox.bind('<KeyPress>', self.handle_keypress)
        self.window.bind('<KeyPress>', self.handle_window_keypress)

        self.status_label = ttk.Label(self.right_frame, text='')
        self.status_label.pack(side="left",pady=5)

        self.author_label = ttk.Label(self.right_frame, text='by LZH')
        self.author_label.pack(side='right', padx=5, pady=5)

        self.load_section_tags()
        self.load_tag_texts()
        self.update_tag_listbox()
        self.update_section_buttons()

        self.switch_section(self.current_section)

        self.window.bind('<Control-Shift_L>', self.switch_to_live_section)
        self.window.bind('<Control-Shift_R>', self.switch_to_live_section)

    def import_txt(self):
        file_path = filedialog.askopenfilename(filetypes=[("Text Files", "*.txt")])
        if file_path:
            with open(file_path, 'r', encoding='utf-8') as file:
                lines = file.readlines()
                tag_selection = self.tag_listbox.curselection()
                if not tag_selection:
                    messagebox.showwarning('警告', '请先选择一个标签')
                    return

                tag = self.tag_listbox.get(tag_selection[0])
                section_tag_key = f"{self.current_section}_{tag}"

                if section_tag_key not in self.tag_texts:
                    self.tag_texts[section_tag_key] = []

                for line in lines:
                    text = line.strip()
                    if text and text not in self.tag_texts[section_tag_key]:
                        self.tag_texts[section_tag_key].append(text)

                self.save_tag_texts()
                self.on_tag_select(None)  # 刷新显示

    def export_txt(self):
        tag_selection = self.tag_listbox.curselection()
        if not tag_selection:
            messagebox.showwarning('警告', '请先选择一个标签')
            return

        tag = self.tag_listbox.get(tag_selection[0])
        section_tag_key = f"{self.current_section}_{tag}"
        if section_tag_key not in self.tag_texts or not self.tag_texts[section_tag_key]:
            messagebox.showwarning('警告', '该标签下没有文本内容')
            return

        file_path = f"{self.current_section}-{tag}.txt"
        with open(file_path, 'w', encoding='utf-8') as file:
            for text in self.tag_texts[section_tag_key]:
                file.write(text + '\n')

        messagebox.showinfo('提示', f'文本已导出到 {file_path}')

    def load_tag_texts(self):
        key = load_key()
        if os.path.exists('tag_texts.json'):
            try:
                with open('tag_texts.json', 'rb') as f:
                    encrypted_data = f.read()
                data = decrypt_data(encrypted_data, key)
                self.tag_texts = json.loads(data)
            except:
                self.tag_texts = {}

    def save_tag_texts(self):
        key = load_key()
        data = json.dumps(self.tag_texts, ensure_ascii=False)
        encrypted_data = encrypt_data(data, key)
        with open('tag_texts.json', 'wb') as f:
            f.write(encrypted_data)

    def load_section_tags(self):
        key = load_key()
        for section in self.sections:
            tag_file = f'tags_{section}.json'
            if os.path.exists(tag_file):
                try:
                    with open(tag_file, 'rb') as f:
                        encrypted_data = f.read()
                    data = decrypt_data(encrypted_data, key)
                    self.section_tags[section] = json.loads(data)
                except:
                    self.section_tags[section] = []

    def save_section_tags(self):
        key = load_key()
        tag_file = f'tags_{self.current_section}.json'
        data = json.dumps(self.section_tags[self.current_section], ensure_ascii=False)
        encrypted_data = encrypt_data(data, key)
        with open(tag_file, 'wb') as f:
            f.write(encrypted_data)

    def add_tag(self, event=None):
        tag = self.tag_input.get().strip()
        if tag and tag not in self.section_tags[self.current_section]:
            self.section_tags[self.current_section].append(tag)
            self.tag_texts[tag] = []
            self.save_section_tags()
            self.save_tag_texts()
            self.update_tag_listbox()
            self.tag_input.delete(0, tk.END)

            index = self.section_tags[self.current_section].index(tag)
            self.tag_listbox.selection_set(index)
            self.tag_listbox.event_generate('<<ListboxSelect>>')
            self.tag_input.delete(0, tk.END)

        else:
            messagebox.showwarning('警告', '请输入有效的标签名称')

    def delete_tag(self):
        selection = self.tag_listbox.curselection()
        if selection:
            tag = self.tag_listbox.get(selection[0])
            if messagebox.askyesno('确认', f'确定要删除标签"{tag}"及其所有文本吗?'):
                self.section_tags[self.current_section].remove(tag)
                section_tag_key = f"{self.current_section}_{tag}"
                if section_tag_key in self.tag_texts:
                    del self.tag_texts[section_tag_key]
                self.save_section_tags()
                self.save_tag_texts()
                self.update_tag_listbox()
                self.listbox.delete(0, tk.END)

                self.tag_listbox.selection_set(0)
                self.tag_listbox.event_generate('<<ListboxSelect>>')
                self.tag_input.delete(0, tk.END)

        else:
            messagebox.showwarning('警告', '请先选择要删除的标签')

    def rename_tag(self, event):
        selection = self.tag_listbox.curselection()
        if selection:
            index = selection[0]
            old_tag = self.tag_listbox.get(index)
            
            for widget in self.rename_frame.winfo_children():
                widget.destroy()
            
            entry = ttk.Entry(self.rename_frame, width=25)
            entry.insert(0, old_tag)
            entry.selection_range(0, tk.END)
            entry.pack(side='left', padx=2)
            
            def on_entry_return(event):
                new_tag = entry.get().strip()
                if new_tag and new_tag != old_tag and new_tag not in self.section_tags[self.current_section]:
                    self.section_tags[self.current_section][index] = new_tag
                    old_section_tag_key = f"{self.current_section}_{old_tag}"
                    new_section_tag_key = f"{self.current_section}_{new_tag}"
                    if old_section_tag_key in self.tag_texts:
                        self.tag_texts[new_section_tag_key] = self.tag_texts.pop(old_section_tag_key)
                    self.save_section_tags()
                    self.save_tag_texts()
                    self.update_tag_listbox()
                    self.tag_listbox.selection_set(index)
                    self.tag_listbox.event_generate('<<ListboxSelect>>')
                else:
                    messagebox.showwarning('警告', '请输入有效的标签名称')
                for widget in self.rename_frame.winfo_children():
                    widget.destroy()
            
            entry.bind('<Return>', on_entry_return)
            entry.bind('<FocusOut>', lambda event: entry.destroy())
            entry.focus_set()

    def update_tag_listbox(self):
        self.tag_listbox.delete(0, tk.END)
        for tag in self.section_tags[self.current_section]:
            self.tag_listbox.insert(tk.END, tag)

    def export_all_configs(self):
        # 导出所有分区的标签和文本
        all_configs = {
            'section_tags': self.section_tags,
            'tag_texts': self.tag_texts
        }
        file_path = filedialog.asksaveasfilename(defaultextension=".json", filetypes=[("JSON Files", "*.json")])
        if file_path:
            with open(file_path, 'w', encoding='utf-8') as file:
                json.dump(all_configs, file, ensure_ascii=False, indent=4)
            messagebox.showinfo('提示', f'所有配置已导出到 {file_path}')

    def show_tag_menu(self, event):
        try:
            self.tag_listbox.selection_clear(0, tk.END)
            self.tag_listbox.selection_set(self.tag_listbox.nearest(event.y))
            self.tag_menu.post(event.x_root, event.y_root)
        finally:
            self.tag_menu.grab_release()

    def move_tag_to_section(self, target_section):
        selection = self.tag_listbox.curselection()
        if selection:
            tag = self.tag_listbox.get(selection[0])
            if target_section != self.current_section:
                self.section_tags[self.current_section].remove(tag)
                self.section_tags[target_section].append(tag)
                section_tag_key = f"{self.current_section}_{tag}"
                new_section_tag_key = f"{target_section}_{tag}"
                if section_tag_key in self.tag_texts:
                    self.tag_texts[new_section_tag_key] = self.tag_texts.pop(section_tag_key)
                self.save_section_tags()
                self.save_tag_texts()
                self.update_tag_listbox()
                self.listbox.delete(0, tk.END)
                self.tag_listbox.selection_set(0)
                self.tag_listbox.event_generate('<<ListboxSelect>>')
            else:
                messagebox.showwarning('警告', '标签已在当前区')
        else:
            messagebox.showwarning('警告', '请先选择一个标签')

    def on_tag_select(self, event):
        selection = self.tag_listbox.curselection()
        if selection:
            tag = self.tag_listbox.get(selection[0])
            self.listbox.delete(0, tk.END)
            section_tag_key = f"{self.current_section}_{tag}"
            if section_tag_key in self.tag_texts:
                for text in self.tag_texts[section_tag_key]:
                    self.listbox.insert(tk.END, text)

    def handle_keypress(self, event):
        if event.char == 'd' or event.char == 'D':
            current_time = event.time
            if current_time - self.last_key_time < 500:
                self.delete_text()
            self.last_key_time = current_time

    def handle_window_keypress(self, event):
        if event.char == 'a' or event.char == 'A':
            current_time = event.time
            if current_time - self.last_key_time < 500:
                self.text_input.focus()
            self.last_key_time = current_time

    def add_text(self):
        text = self.text_input.get().strip()
        if not text:
            messagebox.showwarning('警告', '请输入文本内容')
            return

        if len(text) > 100:
            messagebox.showwarning('警告', '文本长度不能超过50个字符')
            return

        tag_selection = self.tag_listbox.curselection()
        if not tag_selection:
            messagebox.showwarning('警告', '请先选择一个标签')
            return

        tag = self.tag_listbox.get(tag_selection[0])
        section_tag_key = f"{self.current_section}_{tag}"
        if text not in self.tag_texts.get(section_tag_key, []):
            if section_tag_key not in self.tag_texts:
                self.tag_texts[section_tag_key] = []
            self.tag_texts[section_tag_key].append(text)
            self.save_tag_texts()
            self.on_tag_select(None)
            self.text_input.delete(0, tk.END)

            self.tag_listbox.selection_set(tag_selection[0])
            self.tag_listbox.event_generate('<<ListboxSelect>>')
        else:
            messagebox.showinfo('提示', '该文本已存在') 

    def delete_text(self):
        selection = self.listbox.curselection()
        if selection:
            text = self.listbox.get(selection[0])
            if messagebox.askyesno('确认', f'确定要删除"{text}"吗?'):
                for tag, texts in self.tag_texts.items():
                    section_tag_key = (self.current_section, tag)
                    if text in texts:
                        texts.remove(text)
                        self.save_tag_texts()
                        break
                self.on_tag_select(None)
                self.listbox.delete(selection[0])
        else:
            messagebox.showwarning('警告', '请先选择要删除的文本')

    def on_select(self, event):
        if event.widget.curselection():
            selection = event.widget.curselection()
            if selection:
                text = event.widget.get(selection[0])
                pyperclip.copy(text)
                display_text = text if len(text) <= 20 else f"{text[:10]}...{text[-10:]}"
                self.status_label.config(text=f'"{display_text}"已复制到剪贴板')
                self.window.after(2000, lambda: self.status_label.config(text=''))

                self.listbox.itemconfig(selection[0], {'bg': 'yellow'})
                for i in range(self.listbox.size()):
                    if i != selection[0]:
                        self.listbox.itemconfig(i, {'bg': 'white'})

    def update_section_buttons(self):
        for section, btn in self.section_buttons.items():
            if section == self.current_section:
                btn.configure(style='Selected.TButton')
            else:
                btn.configure(style='Normal.TButton')

    def switch_to_live_section(self, event):
        self.current_section = 'Live'
        self.update_tag_listbox()
        self.listbox.delete(0, tk.END)
        self.window.title(f'文本管理器 - Live')
        self.update_section_buttons()

        if self.tag_listbox.size() > 0:
            self.tag_listbox.selection_set(0)
            self.tag_listbox.event_generate('<<ListboxSelect>>')

    def switch_section(self, section):
        if section == 'Live':
            password = simpledialog.askstring("密码", "请输入密码:", show='*')
            if password != "your_password_here":
                return
        self.current_section = section
        self.update_tag_listbox()
        self.listbox.delete(0, tk.END)
        self.window.title(f'文本管理器 - {section}')
        self.update_section_buttons()

        if self.tag_listbox.size() > 0:
            self.tag_listbox.selection_set(0)
            self.tag_listbox.event_generate('<<ListboxSelect>>')

    def run(self):
        self.window.mainloop()

if __name__ == '__main__':
    app = TextManager()
    app.run()